package com.lanhai.longheng.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map; 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import com.lanhai.longheng.beans.DeviceBean;
import com.lanhai.longheng.beans.DeviceMountBean;
import com.lanhai.longheng.dao.DeviceDao;
import com.lanhai.longheng.dao.DeviceGroupDao; 
import com.lanhai.longheng.enums.TransDirectionEnum;
import com.lanhai.longheng.interfaces.IDevice;
import com.lanhai.longheng.interfaces.IDeviceMount;
import com.lanhai.longheng.mapper.DeviceMapper; 
 

/**
 * 设备相关
 * @author zhengwei
 *
 */
@Service 
public class DeviceImpl implements IDevice {
 
	
	@Autowired
	DeviceMapper deviceMapper;
	
	@Autowired
	IDeviceMount deviceMount;
	
	
	
	  
	//缓存，减少从redis中拿数据的可能性
	//DeviceBean 对应的是表内的基础数据，没有变更属性，不需要放redis中 
	//IP：设备
	 static Map<String,DeviceBean> ipMap=  Collections.synchronizedMap(new HashMap<String,DeviceBean>()); 
	//点位：设备
	 static Map<Integer,DeviceBean> dotMap=  Collections.synchronizedMap(new HashMap<Integer,DeviceBean>());
	//IP:指令
	static Map<String,String> cmdMap=  Collections.synchronizedMap(new HashMap<String,String>());
	
 
	/**
	 * 先缓存后mysql。此方法拿到的对象不用于传输判断
	 */
	@Override
	public synchronized DeviceBean getDao(String ip,  int line) { 
		String key=String.format("%s_%d", ip,line); 
		DeviceBean bean=ipMap.get(key);
		if(bean==null) {
			DeviceDao dao = deviceMapper.getObj(ip, line);
			if (dao != null) {
				bean = transDaoToBean(dao);  
				cmdMap.put(bean.getIp(), bean.getCmdSign());
				ipMap.put(key, bean);
			}
		} 
		return bean;
	}
 
	DeviceBean transDaoToBean(DeviceDao dao) { 
		DeviceBean	bean = new DeviceBean();
		bean.setCmdSign(dao.getCmdSign());
		bean.setDeviceGroup(dao.getDeviceGroup());
		bean.setDeviceid(dao.getId()); 
		bean.setSpecialline(dao.getSpecialline());
		bean.setDotNO(dao.getDotNO());
		bean.setIp(dao.getIp());
		bean.setPort(dao.getPort());
		bean.setLeastnum(dao.getLeastnum());
		bean.setLine(dao.getLine());
		bean.setProcess(dao.getProcess());
		bean.setProcessGroup(dao.getProcessGroup());
		if (dao.getTransType() == 1) {
			bean.setUpTrans(true);
			bean.setDownTrans(false);
		} else if (dao.getTransType() == 2) {
			bean.setUpTrans(false);
			bean.setDownTrans(true);
		} else {
			bean.setUpTrans(true);
			bean.setDownTrans(true);
		}
		bean.setFillType(TransDirectionEnum.getTransDirectionEnum(dao.getFilltype()));
		return bean;
	}
	
	
	/**
	 * 从点位拿机台， 从db中获取实时数据，涉及到传输
	 * 
	 */
	@Override
	public   DeviceBean getDaoByDot(int dotNO,boolean cache) {  
		DeviceBean bean=null;
		if(cache==false)
		{
			//从db中读取
			DeviceDao dao = deviceMapper.getObjByDotNo(dotNO);
			if (dao != null) {
				bean = transDaoToBean(dao); 
			}
		}else {
			//读缓存
			bean = dotMap.get(dotNO); 
			if(bean==null) { 
				DeviceDao dao = deviceMapper.getObjByDotNo(dotNO);
				if (dao != null) {
					bean = transDaoToBean(dao);
					dotMap.put(dotNO, bean);
				}
			}
		
		} 
		return bean;
		
	}

	@Override
	public synchronized String getCmdSign(String ip) {
		String cmd = cmdMap.get(ip);
		if (cmd != null && cmd.length() > 0) {
			return cmd;
		} 
		// 拿不到就去数据库里面拿
		cmd = deviceMapper.getCmdSign(ip);
		if (cmd != null && cmd.length() > 0) {
			cmdMap.put(ip, cmd);
		}
		return cmd;
	}

	@Override
	public  synchronized void updateError(long deviceid) {
		// TODO Auto-generated method stub
		//deviceMapper
		//机台异常，不管
	}
 
 
	
	/**
	 *通过数量找到机台
	 */ 
	@Override
	public synchronized DeviceGroupDao findNextDevice(int agvid, String nextProcess,int specialline )
	{
		List<DeviceGroupDao> list;
		boolean sline=false; //定线标识
		if(nextProcess.contains("制绒上")) {
			//制绒上料没有定线 
			list=deviceMapper.getEmptyList(nextProcess,0);
			sline=false;
		}else {
			//找定线的+混料的.  
			list=deviceMapper.getEmptyList(nextProcess,specialline);
			 if(specialline>0) {
				 sline=true;
			 }
		}
		  
		if (list == null || list.size() == 0) {
			return null;
		}
		List<DeviceGroupDao> tmp=new ArrayList<DeviceGroupDao>(); 
		TransDirectionEnum	transType =	getTransType(nextProcess);
		for(DeviceGroupDao item:list) {
			 
			DeviceMountBean bean = deviceMount.getBean(item.getDeviceid());
			if (bean == null) {
				continue;
			} 
			if (transType == TransDirectionEnum.OnlyIn && bean.getInNum() >= item.getLeastnum()) {
				item.setNum(bean.getInNum());
				item.setInnum(bean.getInNum()); 
				item.setSpecialline( sline?bean.getSpecialline():0);
				tmp.add(item);
			}
			if (transType == TransDirectionEnum.OnlyOut && bean.getOutNum() >= item.getLeastnum()) {
				item.setNum(bean.getOutNum());
				item.setSpecialline( sline?bean.getSpecialline():0);
				tmp.add(item);
			}
			if (transType == TransDirectionEnum.Both) {
				int max=14;
				if(nextProcess.contains("SE")) {
					max=12;  //激光里面最多有两个，其它长皮带是4个
				}
				int numcount=10-bean.getInNum() + bean.getOutNum(); //现有花篮数
				//花篮总数量必须在8-12之间
				if (numcount>=8 && numcount<=max &&(  bean.getInNum() + bean.getOutNum() >= item.getLeastnum())) {
					item.setNum(bean.getInNum() + bean.getOutNum());
					item.setInnum(bean.getInNum()); 
					item.setSpecialline( sline?bean.getSpecialline():0);
					tmp.add(item);
				}
			}
		} 
		if(tmp.size()>0) {
			//定线优先，其次才是数量
			Collections.sort(tmp, new Comparator<DeviceGroupDao>() { 
				@Override
				public int compare(DeviceGroupDao o1, DeviceGroupDao o2) {
					//先进料数量降序，其次总数量降序，最后传输时间升序
					if(o1.getInnum()==o2.getInnum()) {
						if(o1.getNum()==o2.getNum()) {
							return (int)( o1.getLasttime()-o2.getLasttime());
						}else {
							return o2.getNum()-o1.getNum();
						}
					}else {
						return o2.getInnum()-o1.getInnum();
					}
				  
				}
			});
			for(DeviceGroupDao da:tmp) {
				System.out.println(String.format("dotno=%d num=%d spline=%d", da.getDotno(),da.getNum(),da.getSpecialline()));
			}
			return tmp.get(0);
		} 
		return null;
	 
	}
	 


	//工位加锁解锁
	@Override
	public   void unlockForAgv(int agvId) {
		 deviceMapper.unlockForAgv(agvId);
	}

	@Override
	public   void lockDevice(long deviceid,int agvId) {
		deviceMapper.lockDevice(deviceid, agvId); 
	}

	@Override
	public  void lockDeviceForTrans(long deviceid, int agvId) {
		deviceMapper.lockDevice(deviceid, agvId);
		deviceMapper.clearOtherDevice(deviceid, agvId);
	}
	/**
	 * 点位释放
	 */
	@Override
	public  void unlockDeviceForDot(int dotno,int agvId) {
		  deviceMapper.unlockDeviceByDot(dotno,agvId,System.currentTimeMillis() );
		  
	}




	@Override
	public synchronized DeviceBean getDaoByID(long deviceid) {
		DeviceBean bean=null;
		DeviceDao dao = deviceMapper.getObjById(deviceid);
		if (dao != null) {
			bean = transDaoToBean(dao); 
		}
		return bean; 
	}




	@Override
	public synchronized void unlockDeviceById(long id) {
		 deviceMapper.unlockDeviceById(id,System.currentTimeMillis()); 
	}
 

	@Override
	public synchronized DeviceGroupDao findLockDeviceForAgv(int agvid,String processgroup) {
	 
		return deviceMapper.findLockDeviceForAgv(agvid,processgroup);
	}
 
	@Override
	public synchronized DeviceGroupDao findNextDeviceNospecialline(int agvid, String nextProcess) {
		List<DeviceGroupDao> list = deviceMapper.getEmptyListForDecide(nextProcess); 
		if (list == null || list.size() == 0) {
			return null;
		}
		TransDirectionEnum	transType =	getTransType(nextProcess);
		
		List<DeviceGroupDao> tmp=new ArrayList<DeviceGroupDao>(); 
		for(DeviceGroupDao item:list) {
			 
			DeviceMountBean bean = deviceMount.getBean(item.getDeviceid());
			if (bean == null) {
				continue;
			}
			if (transType == TransDirectionEnum.OnlyIn && bean.getInNum() >= item.getLeastnum()) {
				item.setNum(bean.getInNum());
				item.setInnum(bean.getInNum()); 
				tmp.add(item);
			}
			if (transType == TransDirectionEnum.OnlyOut && bean.getOutNum() >= item.getLeastnum()) {
				item.setNum(bean.getOutNum());
				tmp.add(item);
			}
			if (transType == TransDirectionEnum.Both) {
				int max=14;
				if(nextProcess.contains("SE")) {
					max=12;  //激光里面最多有两个，其它长皮带是4个
				}
				int numcount=10-bean.getInNum() + bean.getOutNum(); //现有花篮数
				//花篮总数量必须在8-12之间
				if ( numcount>=8 && numcount<=max &&(  bean.getInNum() + bean.getOutNum() >= item.getLeastnum())) {
					item.setNum(bean.getInNum() + bean.getOutNum());
					item.setInnum(bean.getInNum()); 
					tmp.add(item);
				}
			}
		} 
		if(tmp.size()>0) {
			//排序，取第一个
			Collections.sort(tmp, new Comparator<DeviceGroupDao>() { 
				@Override
				public int compare(DeviceGroupDao o1, DeviceGroupDao o2) {
					// o1-o2是升序
					//先进料数量降序，其次总数量降序，最后传输时间升序
					if(o1.getInnum()==o2.getInnum()) {
						if(o1.getNum()==o2.getNum()) {
							return (int)( o1.getLasttime()-o2.getLasttime());
						}else {
							return o2.getNum()-o1.getNum();
						}
					}else {
						return o2.getInnum()-o1.getInnum();
					}
				  
				}
			});
			return tmp.get(0);
		} 
		return null;
	}

	
	/**
	 * 解锁目标机台外的其它机台
	 */
	@Override
	public synchronized void unlockOtherDevice(long deviceid, int agvId) {
		deviceMapper.clearOtherDevice(deviceid, agvId);
	}

	
	TransDirectionEnum getTransType(String process) {
		if(process.startsWith("制绒下")) {
			return TransDirectionEnum.OnlyOut;
		}else if(process.startsWith("扩散")) {
			//return TransDirectionEnum.OnlyIn;
		}else if(process.startsWith("制绒上")) {
			return TransDirectionEnum.OnlyIn;
		}
		return TransDirectionEnum.Both;
	}
 
}
